import { getApps } from "..";
import { importHtml } from "../import-html";
import type { IRegisterMicroApp } from "../type";
import { getNextRoute, getPrevRoute } from "./rewrite-router";

// 处理路由变化
export const handleRouter = async () => {
  const apps = getApps();
  // 获取当一个路由
  const prevApp = apps.find((app) => {
    if (app?.activeRule === getPrevRoute()) {
      return null
    }
    return getPrevRoute().startsWith(app.activeRule)
  });
  // 2. 匹配子应用（获取当前路由）
  const app = apps.find((app) => {
    if (app?.activeRule === getPrevRoute()) {
      return null
    }
    // return window.location.pathname.startsWith(app.activeRule)
    return getNextRoute().startsWith(app.activeRule);
  });

  // 如果有上一个应用，先销毁
  if (prevApp) {
    await unmount(prevApp);
  }

  if (!app) {
    return;
  }

  // 3. 加载子应用: 请求获取子应用资源（html、css、js）
  // const html = await fetch(app.entry).then(res => res.text())
  const { template, execScripts } = await importHtml(app.entry);
  const container = document.querySelector(app.container);
  /**
   * 子应用不会渲染:
   * 因为vue、react都是通过js来渲染页面的，而innerHTML中的script，会直接被浏览器忽略掉，不会加载执行
   */
  // container!.innerHTML = html
  container?.appendChild(template);
  // 新增环境变量
  window.__POWERED_BY_QIANKUN__ = true;
  window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__ = app.entry + "/";
  // 所以我们需要手动去执行js代码，可以通过 eval()、new Function() 来实现
  const appExports = await execScripts();
  app.bootstrap = appExports.bootstrap;
  app.mount = appExports.mount;
  app.unmount = appExports.unmount;
  app.update = appExports.update;

  await bootstrap(app);
  await mount(app);

  // 4. 渲染子应用
};

declare global {
  interface Window {
    __POWERED_BY_QIANKUN__: boolean;
    __INJECTED_PUBLIC_PATH_BY_QIANKUN__: string;
  }
}

async function bootstrap(app: IRegisterMicroApp) {
  app.bootstrap && (await app.bootstrap());
}

async function mount(app: IRegisterMicroApp) {
  app.mount &&
    (await app.mount({
      container: document.querySelector(app.container),
    }));
}

async function unmount(app: IRegisterMicroApp) {
  app.unmount &&
    (await app.unmount({
      container: document.querySelector(app.container),
    }));
}
